iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 8
5
Modern Web

成為 Modern PHPer系列 第 8

Day 08:輸出內容的過濾

  • 分享至 

  • xImage
  •  

「絕對不要相信來自於使用者的資料。」

前言

寫 PHP 時常常會聽到一句「絕對不要相信來自於使用者的資料」,這麼多年過去了,SQL Injection、XSS、LFI 等問題在 PHP 上仍然層出不窮。

有人把原因歸咎於 PHP 的語言設計:過於複雜化的內建函式庫。就算是多年 PHP 經驗的老手,也可能會落入一些不是最佳實踐的陷阱。

XSS

XSS,全名 Cross-Site Scripting。簡單來說就是惡意使用者讓網頁渲染出非預期的內容,進而達成某些目的。

<?php

echo 'Hello, '.$_GET['name'];

此時,若我使用 /?name=<script>alert('XSS')</script> 就可以直接跳出一個 alert。

然而,跳出 alert 並非 XSS 主要的危害,通常僅是拿來驗證問題存在的手段。XSS 真正的危險在於:它可以取得這個網站的 cookie 等資訊--這通常是拿來存在使用者憑證的地方。

當然,XSS 的危害不止於盜竊用戶憑證,例如透過今年的 CVE-2019-5786 在 Chrome 上執行後直接在對方電腦執行程式。

錯誤的防禦方式

這邊先舉幾個比較常見的防範 XSS 的錯誤範例。

輸出時移除 "script"

echo str_replace('script', '', $_GET['name']);

破解法:/?name=<sscriptcript>alert('XSS')</sscriptcript>

strip_tags()

echo strip_tags($_GET['name']);

strip_tags 的幾個問題

  • 它不會檢查輸入的內容是否為 HTML,既亦可能產生無法解析的 HTML
  • 對於某些 allowed_tagsstrip_tags 的第二個參數)可能仍然會存在 XSS 問題
echo strip_tags('<img src="a.jpg" onload="alert(1)"/>', '<img>');

上述內容中,<img> 是可使用的 tag,所以內容依然會被輸出,而 onload 事件中可以執行 Javascript,故仍然可以觸發 XSS。

防禦方式

就理論上來說,htmlspecialchars()htmlentities() 都是正確答案。

在 Modern PHP 中使用的是 htmlentities(),而在各大 Framework 的實作上以 htmlspecialchars() 居多。

htmlspecialchars()

htmlspecialchars() 是僅替換需要進行 HTML 編碼的字元(<>&"'

幾個比較知名的 Framework 或 Template Engine 都是使用這個函式:

值得注意的是,在使用這個函式時務必要加上合適的參數。

  • 第二個參數表示使用的規則(替換單、雙引號或無效字元的處理等)
  • 第三個參數表示使用的編碼(通常以 UTF-8 為主)

htmlentities()

htmlentities() 會將所有輸入的內容都進行 HTML 編碼。

這個函式的缺點是如果使用非預期的編碼,可能會造成輸出時仍然存在亂碼或利用編碼問題繞過並達成 XSS。對於 PHP 5.5 (含)以後的預設編碼是 UTF-8;5.4 (含)以前的預設編碼是 ISO-8859-1。

在 Modern PHP 一書中,使用這個函式做輸出內容的編碼,但作者提到一定要注意參數的設置:

  • 要轉換單引號及雙引號(ENT_QUOTES
  • 要設定編碼(UTF-8)

後記

今天的 XSS 算是把之前在 PTT PHP 版上的文章中關於 XSS 的部份稍微拿出來再整理一次。

當時跟 GLINE 大大討論 htmlentities 在某些時候的預設設定是可以用 UTF-7 打穿的,這部份僅僅是帶過而已,這邊再做比較詳細的整理。

該篇文章有我跟 G 大整理出的一系列 PHP 網站資安常見的問答(之後鐵人要是沒東西寫的話也可能拿來整理 XD),可以稍微參考看看:

[請益] 網站資安需注意哪些?
R: [請益] 網站資安需注意哪些?
R: [請益] 網站資安需注意哪些?
R: [請益] 網站資安需注意哪些?


上一篇
Day 07:善用預定義的 interface 及 class
下一篇
Day 09:輸入資料過濾
系列文
成為 Modern PHPer30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言